package org.onion.pattern.event.spring.idempotent;

import com.github.f4b6a3.uuid.UuidCreator;
import org.onion.pattern.event.exception.EventConsumeIdempotentException;
import org.onion.pattern.event.idempotent.EventIdempotentService;
import org.onion.pattern.event.idempotent.IdempotentStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.function.Supplier;

@Component
public class JdbcEventIdempotentService implements EventIdempotentService {

    @Autowired
    private JdbcTemplate        jdbcTemplate;
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Override
    public IdempotentStatus mark(String handlerName,String eventType, String eventKey) {

        String sql = "INSERT INTO _event_idempotent (" +
                " id," +
                " handler_name," +
                " event_key," +
                " event_type," +
                " status) "
                + "VALUES (?, ?, ?, ? ,?)";
        String id = UuidCreator.getTimeOrderedEpoch().toString();

        try {
            this.jdbcTemplate.update(sql, id, handlerName, eventKey,eventType, "");
        } catch (DuplicateKeyException e) {
            return IdempotentStatus.CONSUMED;
        }
        return IdempotentStatus.UNCONSUMED;
    }

    @Override
    public void execute(String handlerName,String eventType, String eventKey, Supplier<?> handle) {
        this.transactionTemplate.execute(transactionStatus -> {
            IdempotentStatus mark = this.mark(handlerName, eventType,eventKey);
            switch (mark) {
                case UNCONSUMED:
                    break;
                default:
                    throw new EventConsumeIdempotentException( handlerName + ": "+eventType +" eventKey "+eventKey);
            }
            return handle.get();
        });
    }


}
